package com.doupi.partner.manager.authenticator.filter;

import com.doupi.partner.dal.model.Administrator;
import com.doupi.partner.dal.model.AdministratorHasRole;
import com.doupi.partner.dal.model.AdministratorPermission;
import com.doupi.partner.dal.model.AdministratorRoleHasPermission;
import com.doupi.partner.manager.authenticator.athuc.AutoLoginToken;
import com.doupi.partner.model.PartnerRelation;
import com.doupi.partner.service.*;
import com.doupi.partner.util.constant.UtilConstants;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.*;

/**
 * web 过滤器 基本
 * 
 * @author Alvin Wang
 * @version 1.0.0 on 2017-04-04
 */
public abstract class BaseAuthenticationFilter extends FormAuthenticationFilter {

	private final AdministratorPermissionService administratorPermissionService;

	private final AdministratorHasRoleService administratorHasRoleService;

	private final AdministratorRoleHasPermissionService administratorRoleHasPermissionService;

	protected final PartnerRelationService partnerRelationService;

	protected final AdministratorService administratorService;

	public BaseAuthenticationFilter(AdministratorPermissionService administratorPermissionService, AdministratorHasRoleService administratorHasRoleService,
			AdministratorRoleHasPermissionService administratorRoleHasPermissionService, PartnerRelationService partnerRelationService, AdministratorService administratorService) {
		this.administratorPermissionService = administratorPermissionService;
		this.administratorHasRoleService = administratorHasRoleService;
		this.administratorRoleHasPermissionService = administratorRoleHasPermissionService;
		this.partnerRelationService = partnerRelationService;
		this.administratorService = administratorService;
	}

	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
		try {
			Administrator administrator = (Administrator) subject.getPrincipal();
			Session session = subject.getSession();
			Set<AdministratorPermission> menus = new LinkedHashSet<>();
			List<AdministratorPermission> administratorPermissions = selectAdministratorPermissionsByUserId(administrator.getId());
			for (AdministratorPermission administratorPermission : administratorPermissions) {
				if (administratorPermission.getType() == 1) {
					menus.add(administratorPermission);
				}
			}
			List<AdministratorPermission> sortList = new ArrayList<>();
			sortList.addAll(menus);
			sortList.sort(Comparator.comparingInt(AdministratorPermission::getOrderIndex));
			Collections.reverse(sortList);
			session.setAttribute(UtilConstants.CURRENT_USER_MENU, sortList);
			session.setAttribute(UtilConstants.CURRENT_USER, administrator);

			if (!token.getClass().isAssignableFrom(AutoLoginToken.class)) { // 非自动登录
				// 绑定微信openId
				String openId = WebUtils.getCleanParam(request, "openId");
				if (StringUtils.isNotBlank(openId)) {
					PartnerRelation partnerRelation = partnerRelationService.selectByAdministratorId(administrator.getId());

					partnerRelation.setOpenId(openId);
					partnerRelationService.updateByPrimaryKeySelective(partnerRelation);
				}
			}

		} catch (Exception e) {
			throw new IncorrectCredentialsException(e);
		}
		return super.onLoginSuccess(token, subject, request, response);
	}

	private List<AdministratorPermission> selectAdministratorPermissionsByUserId(Long userId) {
		List<AdministratorPermission> administratorPermissions = new ArrayList<>();
		List<AdministratorHasRole> aToArs;
		List<AdministratorRoleHasPermission> arToAps;
		AdministratorPermission administratorPermission;
		try {
			aToArs = administratorHasRoleService.queryByAdministratorId(userId);
			for (AdministratorHasRole aToArTemp : aToArs) {
				arToAps = administratorRoleHasPermissionService.queryByAdministratorRoleId(aToArTemp.getAdministratorRoleId());
				for (AdministratorRoleHasPermission permissionTemp : arToAps) {
					administratorPermission = administratorPermissionService.selectByPrimaryKey(permissionTemp.getAdministratorPermissionId());
					if (administratorPermission != null) {
						administratorPermissions.add(administratorPermission);
					}
				}
			}
		} catch (Exception e) {
			throw new IncorrectCredentialsException(e);
		}
		return administratorPermissions;
	}
}
